package com.drotposta.unitils;

import com.drotposta.unitils.annotation.Principal;
import com.drotposta.unitils.annotation.Servlet;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Dictionary;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.unitils.core.TestListener;

/**
 *
 * @author elek
 */
class UnitilsEjbModuleListener extends TestListener {

    private Directory directory = new Directory();

    public UnitilsEjbModuleListener(String persistenceUnit) {
        directory.setPersistenceUnit(persistenceUnit);
    }

    @Override
    public void beforeTestMethod(Object testObject, Method testMethod) {
        if (testMethod.isAnnotationPresent(Principal.class)) {
            Principal principal = testMethod.getAnnotation(Principal.class);
            directory.setPrincipalName(principal.name());
        }
    }

    @Override
    public void afterTestMethod(Object testObject, Method testMethod, Throwable testThrowable) {
        directory.resetEm();
    }

    @Override
    public void beforeTestSetUp(Object testObject, Method testMethod) {
        Class beanClazz = testObject.getClass();
        for (Field field : beanClazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(EJB.class)) {
                try {
                    Object ejb = new EjbFactory(field.getType(), directory).getEjb();
                    field.setAccessible(true);
                    field.set(testObject, ejb);
                } catch (Exception ex) {
                    Logger.getLogger(UnitilsEjbModuleListener.class.getName()).log(Level.SEVERE, null, ex);
                    throw new RuntimeException("Initialization error");
                }

            } else if (field.isAnnotationPresent(PersistenceContext.class)) {
                try {
                    String unitName = field.getAnnotation(PersistenceContext.class).unitName();
                    field.setAccessible(true);
                    field.set(testObject, directory.getEntityManager(unitName));
                } catch (Exception ex) {
                    Logger.getLogger(UnitilsEjbModuleListener.class.getName()).log(Level.SEVERE, null, ex);
                    throw new RuntimeException("Initialization error");
                }
            } else if (field.isAnnotationPresent(Servlet.class)) {
                try {
                    field.setAccessible(true);
                    field.set(testObject, new ServletFactory(field.getType(), directory).getServlet());
                } catch (Exception ex) {
                    Logger.getLogger(UnitilsEjbModuleListener.class.getName()).log(Level.SEVERE, null, ex);
                    throw new RuntimeException("Initialization error", ex);
                }
            }
        }

    }
}
